package com.shen.library_nettysocket.handler

import io.netty.channel.ChannelInboundHandlerAdapter
import io.netty.channel.ChannelHandlerContext
import com.alibaba.fastjson.JSONObject
import com.shen.library_nettysocket.IMSConfig
import com.shen.library_nettysocket.netty.NettyTcpClient
import com.shen.library_nettysocket.protobuf.MessageProtobuf
import io.netty.util.internal.StringUtil
import java.lang.Exception
import java.util.*

/**
 * 消息接收处理handler
 */
class TCPReadHandler(private val imsClient: NettyTcpClient) : ChannelInboundHandlerAdapter() {

    /**
     * 通道 非活跃（断开） -- 重连
     */
    @Throws(Exception::class)
    override fun channelInactive(ctx: ChannelHandlerContext) {
        super.channelInactive(ctx)
        System.err.println("TCPReadHandler channelInactive()")
        closeAndResetConnect(ctx)
    }

    /**
     * 出现异常 -- 重连
     */
    @Throws(Exception::class)
    override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
        super.exceptionCaught(ctx, cause)
        System.err.println("TCPReadHandler exceptionCaught()")
        closeAndResetConnect(ctx)
    }

    private fun closeAndResetConnect(ctx: ChannelHandlerContext){
        ctx.channel()?.apply {
            close()
            ctx.close()
        }
        imsClient.resetConnect(false)               // 触发重连
    }

    @Throws(Exception::class)
    override fun channelRead(ctx: ChannelHandlerContext, msg: Any?) {
        if(msg !is MessageProtobuf.Msg?) return
        val message: MessageProtobuf.Msg? = msg
        if (message?.head == null) return

        when(message.head.msgType){
            imsClient.serverSentReportMsgType -> {
                val statusReport: Int = message.head.statusReport
                println(String.format("服务端状态报告：「%d」, 1代表成功，0代表失败", statusReport))

                if (statusReport == IMSConfig.DEFAULT_REPORT_SERVER_SEND_MSG_SUCCESSFUL) {
                    println("收到服务端消息发送状态报告，message=$message，从超时管理器移除")
                    imsClient.msgTimeoutTimerManager?.remove(message.head.msgId)
                }
            }
            else -> {
                // 其它消息
                // 收到消息后，立马给服务端回一条消息接收状态报告
                println("收到消息，message=$message")
                buildReceivedReportMsg(message.head.msgId)?.apply {
                    imsClient.sendMsg(this)
                }
            }
        }

        imsClient.msgDispatcher?.receivedMsg(message)       // 接收消息，由「消息转发器」转发到「应用层」
    }

    /**
     * 构建「客户端」·「消息接收状态报告」
     * @param msgId
     * @return
     */
    private fun buildReceivedReportMsg(msgId: String?): MessageProtobuf.Msg? {
        if (msgId.isNullOrEmpty()) {
            return null
        }
        val builder: MessageProtobuf.Msg.Builder = MessageProtobuf.Msg.newBuilder()

        val headBuilder: MessageProtobuf.Head.Builder = MessageProtobuf.Head.newBuilder()
        headBuilder.msgId = UUID.randomUUID().toString()
        headBuilder.msgType = imsClient.clientReceivedReportMsgType
        headBuilder.timestamp = System.currentTimeMillis()
        val jsonObj = JSONObject()
        jsonObj["msgId"] = msgId
        headBuilder.extend = jsonObj.toString()

        builder.head = headBuilder.build()
        return builder.build()
    }
}